Ext.namespace('NG.command');

/**
 * 
 * @class NG.command.Session
 * @extends Ext.util.Observable
 */
NG.command.Session = Ext.extend(Ext.util.Observable, {

	loggedURL: "",
	userName: "",
	sessionID: "",

	getSessionID: function (){
		return this.sessionID;
	},
	
	isValid: function(){
		return !Ext.isEmpty(this.getSessionID());
	},

	constructor: function(config){
		config = config || {};
		NG.command.Session.superclass.constructor.call(this, config);
	}
});

/**
 * ServiceRequester singleton
 */
NG.command.ServiceRequester = function(){
	
    /**
     * @private
     * insert session to map if not exists, if exists updates sessionID property of object in map 
     */
    function insertSession(loginURL, userName, sessionID) {
    	var key = loginURL + userName;
    	if (!NGServiceRequester.sessionMap.containsKey(key)) {
    		var session = new NGSession({
	    		loggedURL:loginURL,
	    		userName:userName,
	    		sessionID:sessionID	    		
    		});
    		NGServiceRequester.sessionMap.add(key, session);
    	} else {
    		var session = NGServiceRequester.sessionMap.get(key);
    		session.sessionID = sessionID;
    		NGServiceRequester.sessionMap.replace(key, session);
    	}
    }
 
    return Ext.apply(new Ext.util.Observable, {
    	
    	constructor: function(config){
    		Ext.util.Observable.constructor.call(this, config);
    	},

	 	sessionMap: new Ext.util.HashMap(),

	    /**
	     * Logins to url with userName and password<br>
	     * call isAlreadyLoggedIn(userName, loginURL) before call login 
		 * 
		 * loginSuccess, loginFail events are triggered
		 * 
	     * @asynchronize method
	     * @param {String} userName
	     * @param {String} password
	     * @param {String} loginURL
	     * @param {Object} delegator 
	     */
	    login: function (userName, password, loginURL, delegator, showLoading) {
	    	showLoading = Ext.isEmpty(showLoading) ? true : showLoading;
	    	NGLogger.info("Login URL: " + loginURL);
	    	NGLogger.info("Username: " + userName + ", Password: " + password);
			var req = Ext.Ajax.request({
				url: loginURL,
				showLoading: showLoading,
				params: {
					UserName: userName,
					Password: password
				},
				//defaultHeaders: "Content-Type:application/x-www-form-urlencoded; charset=UTF-8",
				//headers:'Access-Control-Allow-Origin: *',
				method: 'POST',
				success: function(response, opts) {
					var xmlStr = response.responseText;
					//alert('success');
					NGLogger.info(xmlStr);
					xmlStr = xmlStr.substring(xmlStr.indexOf('<?xml version="1.0"'));
					NGLogger.info("xmlstr->" + xmlStr);
					var sessionID = fleegix.xml.parse(fleegix.xml.createDoc(xmlStr), 'string').string;
					if (Ext.isEmpty(sessionID)){
						this.failure(response, opts);
						return;
					}
					insertSession(this.url, this.params.UserName, sessionID);
					if (delegator && Ext.isFunction(delegator.loginSuccess))
						delegator.loginSuccess.call(delegator, sessionID); 
				},
				failure: function(response, opts) {
					if (delegator && Ext.isFunction(delegator.loginFail))
						delegator.loginFail.call(delegator, response, opts);
					else {
						alert("Login Failed To " + loginURL + ". Status:"+ response.status);
					}
				}
			});
			return req;
	    },
	    
	    /**
	     * 
	     * @param {} user
	     * @param {} loginURL
	     * @return {} if user has been logged in to loginURL related session object else undefined
	     */
	    isAlreadyLoggedIn: function (userName, loginURL) {
	    	return this.sessionMap.get(loginURL + userName);
	    },   
	    
	    lastException: null,
	    
	    prepareCommandParams: function (command, sessionID) {
	    	if (command.willBePostedForRunXml()) {
	    		return { WorkSpace: command.workspaceName,
						 ServiceName: command.serviceName,
						 SessionID: sessionID, 
						 DataXML: command.getDataXML(),
						 ServiceDependency: command.serviceDependency };
	    	}
	    	else if (command.willBePostedForValidity()) {
	    		return { WorkSpace: command.workspaceName,
						 ServiceName: command.serviceName,
						 SessionID: sessionID };
	    	}
	    	else {
	    		throw "COULD NOT OBTAIN COMMAND TYPE AND PARAMETERS";
	    	}
	    },
	    
		/**
	     * Applies delegator's requestFinished and requestFail methods with responseData as parameter.
	     * command.showLoading property determines whether loading gif will be displayed or not.
	     * 
	     * @param {NG.command.Request} command
	     * @param {} delegator
	     * 
	     */
		executeCommand: function (command, sessionID, delegator, async) {

			if (Ext.isEmpty(async)) async = true;
			NGLogger.info(command.getDataXML());
			NGLogger.info("sessionID:" + sessionID);
			NGLogger.info("workspacename: " + command.workspaceName);
			return Ext.Ajax.request({
				timeout: 120000,
				url: command.getPostUrl(), 
				async : async,
				showLoading: command.showLoading,
				params: this.prepareCommandParams(command, sessionID),
				method: 'POST',
				success: function(response, opts) {
					var xmlData = response.responseText;
					NGLogger.info(xmlData);
					
					xmlData = xmlData.substring(xmlData.indexOf('<?xml version="1.0"'));
					NGLogger.info("xmlstr->" + xmlStr);

					//Exception Handling
					var xmlStr = fleegix.xml.parse(fleegix.xml.createDoc(xmlData), 'string').string;
					var exception = fleegix.xml.parse(fleegix.xml.createDoc(xmlStr), "ServiceException");
					if (!Ext.isEmpty(exception) && !Ext.isEmpty(exception.ServiceException)) {
						this.lastException = exception.ServiceException;
						Ext.Msg.alert("Servis Hatası", "Service Exception: " + this.lastException + "<br\>Command: " + command,
								Ext.emptyFn);
						if (delegator && Ext.isFunction(delegator.requestException))
							delegator.requestException.call(delegator, this.lastException);
						return;
					}
					//!--Exception Handling
					
					//var sessionID = fleegix.xml.parse(fleegix.xml.createDoc(xmlStr), 'string').string;
					if (delegator && Ext.isFunction(delegator.requestFinished))
						delegator.requestFinished.call(delegator, xmlData); //buradan daha sonra response'u dön
				},
				failure: function(response, opts) {
					if (delegator && Ext.isFunction(delegator.requestFail))
						delegator.requestFail.call(delegator, response); //buradan daha sonra response'u dön
					else {
						alert("Fail (" + command.toString() + ") Status:"+ response.status);
					}
				}
			});
		}//!executeCommand
    });
}();

NGSession = NG.command.Session;
NGServiceRequester = NG.command.ServiceRequester;

